package com.tingyukeji.fastpay.data.net;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.widget.Toast;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mcxiaoke.bus.Bus;
import com.tingyukeji.fastpay.R;
import com.tingyukeji.fastpay.data.rsa.Base64;
import com.tingyukeji.fastpay.data.rsa.RSAUtil;
import com.tingyukeji.fastpay.my.utils.MyHelper;
import com.tingyukeji.fastpay.utils.BusRespone;
import com.tingyukeji.fastpay.utils.LogUtils;
import com.tingyukeji.fastpay.utils.MD5;
import com.tingyukeji.fastpay.utils.NetUtils;

import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

import okhttp3.CacheControl;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by Administrator on 2016/11/9.
 */

public class OkHttpUtils {
    public static final String TOKEN_TIMEOUT = "OKHTTPUTILS_TOKEN_TIMEOUT";
    public static final String TOKEN_TIMEOUT_SEND = "OKHTTPUTILS_TOKEN_TIMEOUT_SEND";
    private static OkHttpUtils okHttpUtils = null;
    private Context context;
    private Toast mToast;
    private static OkHttpClient okHttpClient = null;

    public void setContext(Context context) {
        this.context = context;
    }

    public static OkHttpUtils getInstance() {
        if (null == okHttpUtils) {
            okHttpUtils = new OkHttpUtils();
        }
        if (null == okHttpClient) {
            okHttpClient = new OkHttpClient();
        }
        return okHttpUtils;
    }

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (mToast != null) {
                mToast.setText(context.getString(R.string.net_error));
                mToast.show();
                return;
            }
            mToast = Toast.makeText(context, context.getString(R.string.net_error), Toast.LENGTH_SHORT);
            mToast.show();
        }
    };

    public boolean checkNet() {
        if (null != context) {
            boolean netFlag = NetUtils.isConnected(context);
            if (!netFlag) {
                mHandler.sendEmptyMessage(0);
            }
            return netFlag;
        } else {
            return true;
        }
    }

    public void get(String url, Map<String, Object> param, final ReqCallBack.ReqCallBackListener callBackListener) {
        if (!checkNet())
            return;
        if (null != param) {
            try {
                JSONObject json = new JSONObject(param);
                StringBuffer stringBuffer = new StringBuffer("?");
                stringBuffer.append("params=");
                byte[] encryptByte = json.toString().getBytes("UTF-8");
                String encryptStr = RSAUtil.encryptByPublicKey1(encryptByte, RSAUtil.PUBLIC_KEY_1);
                stringBuffer.append(encryptStr);
                url += stringBuffer.toString();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        LogUtils.d("get url=" + url);
        LogUtils.d("get url token = " + getAuthorization());
        CacheControl.Builder builder = new CacheControl.Builder();
        builder.maxAge(5, TimeUnit.MILLISECONDS);
        CacheControl cache = builder.build();
        final Request.Builder requestBuilder = new Request.Builder().cacheControl(cache).url(url);
        requestBuilder.method("GET", null);
//        requestBuilder.addHeader("token", getAuthorization());
//        requestBuilder.addHeader("channelSource", ChannelUtil.getChannel(MainApplication.App.getApplicationContext()));
//        requestBuilder.addHeader("imei", AppUtils.getUniqueDeviceID(MainApplication.App.getApplicationContext()));
        final Request request = requestBuilder.build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                LogUtils.d("error url=" + e.toString());
                try {
//                    if (null != callBackListener)
//                        callBackListener.onFail(context.getString(R.string.request_fail));
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (null == callBackListener) return;
                try {
                    if (response.isSuccessful()) {
                        String bodyStr = response.body().string();
                        String newBodyStr = null;
                        judgeTimeOut(bodyStr);
                        String resultEncrypt = new JsonParser().parse(bodyStr).getAsJsonObject().get("result").getAsString();
                        if (!TextUtils.isEmpty(resultEncrypt)){
                            byte[] decryptByte_2 = RSAUtil.decryptByPrivateKey(Base64.decode(resultEncrypt), RSAUtil.PRIVATE_KEY_2);
                            String decryptStr_2 = new String(decryptByte_2,"UTF-8");
                            newBodyStr = bodyStr.replace("\"" +resultEncrypt + "\"",decryptStr_2);
                        }
                        callBackListener.onSuccess(newBodyStr);
                    } else {
//                        callBackListener.onFail("请求失败！！！");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 判断token是否过期
     *
     * @param bodyStr
     */
    public void judgeTimeOut(final String bodyStr) {
        LogUtils.d("response url= " + bodyStr);
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (!MyHelper.ISLOGIN) {
                    return;
                }
                try {
                    JSONObject jsonObject = new JSONObject(bodyStr);
                    if (jsonObject != null && jsonObject.has("success") && jsonObject.has("code")) {
                        int code = jsonObject.getInt("code");
                        boolean success = jsonObject.getBoolean("success");
                        if (!success && code == 1001) {
                            Bus.getDefault().post(new BusRespone(0, 0, TOKEN_TIMEOUT));
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

    }

    public void post(String url, Map<String, Object> param, final ReqCallBack.ReqCallBackListener callBackListener) {
        if (!checkNet())
            return;
//        JSONObject json = new JSONObject(param);
        if (LogUtils.allowD) {
            if (null != param) {
                try {
                    JSONObject json = new JSONObject(param);
                    StringBuffer stringBuffer = new StringBuffer("?");
                    stringBuffer.append("params=");
                    byte[] encryptByte = json.toString().getBytes("UTF-8");
                    String encryptStr = RSAUtil.encryptByPublicKey1(encryptByte, RSAUtil.PUBLIC_KEY_1);
                    stringBuffer.append(encryptStr);
                    url += stringBuffer.toString();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
            LogUtils.d("post url token = " + getAuthorization());
        }
        CacheControl.Builder builder = new CacheControl.Builder();
        builder.maxAge(5, TimeUnit.MILLISECONDS);
        CacheControl cache = builder.build();
        if (param != null) {
//            param.put("belong", AppUtils.getUID(MainApplication.App.getApplicationContext()));
//            param.put("channelSource", ChannelUtil.getChannel(MainApplication.App.getApplicationContext()));
//            param.put("version",AppUtils.getVersionName(MainApplication.App.getApplicationContext()));
        }
        Request request = new Request.Builder().cacheControl(cache).url(url).post(getReqBody(param))
//                .addHeader("token", getAuthorization())
//                .addHeader("channelSource", ChannelUtil.getChannel(MainApplication.App.getApplicationContext()))
//                .addHeader("imei", AppUtils.getUniqueDeviceID(MainApplication.App.getApplicationContext()))
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                LogUtils.d("error url=" + e.toString());
                try {
//                    if (null != callBackListener)
//                        callBackListener.onFail("请求失败！！！");
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    if (null == callBackListener) return;
                    if (response.isSuccessful()) {
                        String bodyStr = response.body().string();
                        String newBodyStr = null;
                        judgeTimeOut(bodyStr);
                        String resultEncrypt = new JsonParser().parse(bodyStr).getAsJsonObject().get("result").getAsString();
                        if (!TextUtils.isEmpty(resultEncrypt)){
                            byte[] decryptByte_2 = RSAUtil.decryptByPrivateKey(Base64.decode(resultEncrypt), RSAUtil.PRIVATE_KEY_2);
                            String decryptStr_2 = new String(decryptByte_2,"UTF-8");
                            newBodyStr = bodyStr.replace("\"" +resultEncrypt + "\"",decryptStr_2);
                        }
                        callBackListener.onSuccess(newBodyStr);
                    } else {
//                        callBackListener.onFail("请求失败！！！");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public void json(String url, String json, final ReqCallBack.ReqCallBackListener callBackListener) {
        if (!checkNet())
            return;
        if (LogUtils.allowD) {
            LogUtils.d("post url=" + url+json);
            LogUtils.d("post url token = "+getAuthorization());
        }
        CacheControl.Builder builder = new CacheControl.Builder();
        builder.maxAge(5, TimeUnit.MILLISECONDS);
        CacheControl cache = builder.build();

        Request request = new Request.Builder().cacheControl(cache).url(url).post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"),json))
                .addHeader("token",getAuthorization())
//                .addHeader("channelSource",ChannelUtil.getChannel(MainApplication.App.getApplicationContext()))
//                .addHeader("imei",AppUtils.getUniqueDeviceID(MainApplication.App.getApplicationContext()))
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                LogUtils.d("error url=" + e.toString());
                try {
//                    if (null != callBackListener)
//                        callBackListener.onFail("请求失败！！！");
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    if (null == callBackListener) return;
                    if (response.isSuccessful()) {
                        String bodyStr = response.body().string();
                        judgeTimeOut(bodyStr);
                        callBackListener.onSuccess(bodyStr);
                    } else {
//                        callBackListener.onFail("请求失败！！！");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private RequestBody getReqBody(Map<String, Object> param) {
        FormBody.Builder builder = new FormBody.Builder();
        try {
            for (String key : param.keySet()) {
                String s = (String) param.get(key);
                if (s != null) {
                    builder.add(key, s);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return builder.build();
    }

    public static String getAuthorization() {
        if (!MyHelper.ISLOGIN || MyHelper.user.getToken() == null) {
            return "";
        }
        return MyHelper.user.getToken();
    }

    private String getSign(Map<String, Object> map) {
        String sign = "";
        TreeMap<String, Object> treeMap = new TreeMap<>(map);
        final List<String> list = new ArrayList<>();
        for (String key : treeMap.keySet()) {
            list.add(key + "=" + treeMap.get(key));
        }
        for (String item : list) {
            if (TextUtils.isEmpty(sign)) {
                sign = item;
            } else {
                sign = sign + "&" + item;
            }
        }
        return MD5.md5(sign + "&key=0wierwNz").toUpperCase();
    }

    /**
     * 上传文件
     *
     * @param url 接口地址
     * @param paramsMap 参数
     * @param callBack  回调
     * @param <T>
     */
    public <T> void upLoadFile(String url, HashMap<String, Object> paramsMap, final ReqCallBack.ReqCallBackListener callBack) {
        try {
//            paramsMap.put("belong", AppUtils.getUID(MainApplication.App.getApplicationContext()));
//            paramsMap.put("channelSource", ChannelUtil.getChannel(MainApplication.App.getApplicationContext()));
            MultipartBody.Builder builder = new MultipartBody.Builder();
            //设置类型
            builder.setType(MultipartBody.FORM);
            //追加参数
            for (String key : paramsMap.keySet()) {
                Object object = paramsMap.get(key);
                if (!(object instanceof File)) {
                    builder.addFormDataPart(key, object.toString());
                } else {
                    File file = (File) object;
                    if (key.startsWith("file")){
                        builder.addFormDataPart("file", file.getName(), RequestBody.create(null, file));
                    }
                }
            }
            //创建RequestBody
            RequestBody body = builder.build();
            //创建Request
            final Request request = new Request.Builder().url(url).post(body)
                    .addHeader("token", getAuthorization())
//                    .addHeader("channelSource", ChannelUtil.getChannel(MainApplication.App.getApplicationContext()))
//                    .addHeader("imei", AppUtils.getUniqueDeviceID(MainApplication.App.getApplicationContext()))
                    .build();
            //单独设置参数 比如读取超时时间
            final Call call = okHttpClient.newBuilder().writeTimeout(50, TimeUnit.SECONDS).build().newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    LogUtils.d(e.toString());
                    callBack.onFail("上传失败");
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (response.isSuccessful()) {
                        String string = response.body().string();
                        LogUtils.d("response ----->" + string);
                        callBack.onSuccess(string);
                    } else {
                        callBack.onFail("上传失败");
                    }
                }
            });
        } catch (Exception e) {
            LogUtils.d(e.toString());
        }
    }
}
